#ifndef KEYRECOMMANDER_H
#define KEYRECOMMANDER_H

//#include "TcpConnection.h"
#include "Dictionary.h"

#include <set>
#include <queue>
#include <vector>
#include <string>


using std::priority_queue;
using std::string;
using std::set;
using std::vector;



// class TcpConnectionPtr;
// class CandidateResult;
//using TcpConnectionPtr = shared_ptr<TcpConnection>;

struct CandidateResult
{
    string _word;
    int _freq;
    int _dist;
};

struct CompareCandidate {
    bool operator()(const CandidateResult& a, const CandidateResult& b) {
        if (a._dist != b._dist) {
            return a._dist > b._dist;  // 按照 _dist 从小到大排序
        } else if (a._freq != b._freq) {
            return a._freq < b._freq;  // 按照 _freq 从大到小排序
        } else {
            return a._word > b._word;  // 按照 _word 字典序排序
        }
    }
};

class KeyRecommander
{
public:
    // KeyRecommander(string& query, TcpConnectionPtr conn)
    // {
    //     // _dic.doAndQuery();
    //     _dic_res = _dic.doAndQuery(query);
    // }
    
    KeyRecommander(string& query, Dictionary& dic)
    : _queryWord(query)
    , _dic(dic)
    {
        _dic_res = _dic.doAndQuery(query);
    }

    void print() {
        //cout << "print()" << endl;
        for (int i = 0; i < 5; ++i) {
            CandidateResult test = _prique.top();
            cout << test._word << endl;
            _prique.pop();
        }
    }

    void statistic() {
        for (auto& elem : _dic_res) {
            CandidateResult temp_can;
            temp_can._word = elem.first;
            temp_can._freq = elem.second;
            temp_can._dist = distance(_queryWord, elem.first);
            _prique.push(temp_can);
        }
    }
    int distance(const std::string & lhs, const std::string &rhs) {
        //计算最小编辑距离-包括处理中英文
        size_t lhs_len = length(lhs);
        size_t rhs_len = length(rhs);
        int editDist[lhs_len + 1][rhs_len + 1];
        for(size_t idx = 0; idx <= lhs_len; ++idx)
        {
            editDist[idx][0] = idx;
        }
        for(size_t idx = 0; idx <= rhs_len; ++idx)
        {
            editDist[0][idx] = idx;
        }
        std::string sublhs, subrhs;
        for(std::size_t dist_i = 1, lhs_idx = 0; dist_i <= lhs_len; ++dist_i,
            ++lhs_idx)
        {
            size_t nBytes = nBytesCode(lhs[lhs_idx]);
            sublhs = lhs.substr(lhs_idx, nBytes);
            lhs_idx += (nBytes - 1);
            for(std::size_t dist_j = 1, rhs_idx = 0;
                dist_j <= rhs_len; ++dist_j, ++rhs_idx)
            {
                nBytes = nBytesCode(rhs[rhs_idx]);
                subrhs = rhs.substr(rhs_idx, nBytes);
                rhs_idx += (nBytes - 1);
                if(sublhs == subrhs)
                {
                    editDist[dist_i][dist_j] = editDist[dist_i - 1][dist_j -
                        1];
                }
                else
                {
                    editDist[dist_i][dist_j] =
                        triple_min(editDist[dist_i][dist_j - 1] + 1,
                                   editDist[dist_i - 1][dist_j] + 1,
                                   editDist[dist_i - 1][dist_j - 1] + 1);
                }
            }
        }
        return editDist[lhs_len][rhs_len];

    }

    // void response() {
    //     // 要发的关键词
    //     //_conn->sendInLoop("sdf");
    // }

private:
    size_t nBytesCode(const char ch)
    {
        if(ch & (1 << 7))
        {
            int nBytes = 1;
            for(int idx = 0; idx != 6; ++idx)
            {
                if(ch & (1 << (6 - idx)))
                {
                    ++nBytes;
                }
                else
                    break;
            }
            return nBytes;
        }
        return 1;
    }

    std::size_t length(const std::string &str)
    {
        std::size_t ilen = 0;
        for(std::size_t idx = 0; idx != str.size(); ++idx)
        {
            int nBytes = nBytesCode(str[idx]);
            idx += (nBytes - 1);
            ++ilen;
        }

        return ilen;
    }

    int triple_min(const int &a, const int &b, const int &c)
    {
        return a < b ? (a < c ? a : c) : (b < c ? b : c);
    }



private:
    string _queryWord;
    Dictionary & _dic;
    // 判断中英文
    priority_queue<CandidateResult, vector<CandidateResult>, CompareCandidate> _prique;
    //TcpConnectionPtr _conn;
    vector<std::pair<string, int>> _dic_res;
    // 取出字典的pair
};

#endif
